// Contient toutes les spécifications de classes nécessaires
// pour représenter l'arbre abstrait
#ifndef ARBRE_H_
#define ARBRE_H_

#include <vector>
#include <iostream>
#include <iomanip>
using namespace std;

#include "Symbole.h"

////////////////////////////////////////////////////////////////////////////////

class Noeud {
    // classe abstraite dont dériveront toutes les classes servant à représenter l'arbre abstrait
    // Remarque : la classe ne contient aucun constructeur
public:
    virtual int getValeur() = 0; // méthode pure (non implémentée) qui rend la classe abstraite

    virtual void afficher(unsigned short indentation = 0) {
        cout << setw(4 * indentation) << " ";
    }
    // pour afficher un noeud avec un décalage (indentation) proportionnel à son niveau dans l'arbre

    virtual ~Noeud() {
    } // présence d'un destructeur virtuel conseillée dans les classes abstraites
};

////////////////////////////////////////////////////////////////////////////////

class NoeudSeqInst : public Noeud {
    // classe pour représenter un noeud "sequence d'instruction"
    // qui a autant de fils que d'instructions dans la séquence
public:
    NoeudSeqInst(); // construit une séquence d'instruction vide

    ~NoeudSeqInst() {
    } // à cause du destructeur virtuel de la classe Noeud
    int getValeur(); // évalue chaque instruction de la séquence
    void afficher(unsigned short indentation = 0); // affiche la séquence d'instructions
    void ajouteInstruction(Noeud* instruction); // ajoute une instruction à la séquence

private:
    vector<Noeud *> tabInst; // pour stocker les instructions de la séquence
};

////////////////////////////////////////////////////////////////////////////////

class NoeudAffectation : public Noeud {
    // classe pour représenter un noeud "affectation"
    // composé de 2 fils : la variable et l'expression qu'on lui affecte
public:
    NoeudAffectation(Noeud* variable, Noeud* expression); // construit une affectation

    ~NoeudAffectation() {
    } // à cause du destructeur virtuel de la classe Noeud
    int getValeur(); // évalue l'expression et affecte sa valeur à la variable
    void afficher(unsigned short indentation = 0); // affiche l'affectation

private:
    Noeud* variable;
    Noeud* expression;
};

////////////////////////////////////////////////////////////////////////////////

class NoeudSi : public Noeud {
    // classe pour représenter un noeud "sequence d'instruction"
    // qui a autant de fils que d'instructions dans la séquence
public:
    NoeudSi(); // construit une séquence d'instruction vide

    ~NoeudSi() {
    } // à cause du destructeur virtuel de la classe Noeud
    int getValeur(); // évalue chaque instruction de la séquence
    void afficher(unsigned short indentation = 0); // affiche la séquence d'instructions
    void ajouteSi(Noeud* exp,Noeud* seq); // ajoute une instruction à la séquence
    void ajouteSinon(Noeud* seq); // ajoute une instruction à la séquence

private:
    vector<Noeud *> tabexp; // pour stocker les instructions de la séquence
    vector<Noeud *> tabseq; // pour stocker les instructions de la séquence
};

////////////////////////////////////////////////////////////////////////////////

class NoeudSwitch : public Noeud {
    // classe pour représenter un noeud "sequence d'instruction"
    // qui a autant de fils que d'instructions dans la séquence
public:
    NoeudSwitch(Noeud* var); // construit une séquence d'instruction vide

    ~NoeudSwitch() {
    } // à cause du destructeur virtuel de la classe Noeud
    int getValeur(); // évalue chaque instruction de la séquence
    void afficher(unsigned short indentation = 0); // affiche la séquence d'instructions
    void ajouteCase(Noeud* inti,Noeud* seq); // ajoute une instruction à la séquence
private:
    vector<Noeud *> tabint; // pour stocker les instructions de la séquence
    vector<Noeud *> tabseq; // pour stocker les instructions de la séquence
    Noeud* variable;
};

////////////////////////////////////////////////////////////////////////////////
class NoeudInstTq : public Noeud {
    // classe pour représenter un noeud "affectation"
    // composé de 2 fils : la variable et l'expression qu'on lui affecte
public:
    NoeudInstTq(Noeud* exp, Noeud* si); // construit une affectation

    ~NoeudInstTq() {
    } // à cause du destructeur virtuel de la classe Noeud
    int getValeur(); // évalue l'expression et affecte sa valeur à la variable
    void afficher(unsigned short indentation = 0); // affiche l'affectation

private:
    Noeud* expression;
    Noeud* seqInst;
};

class NoeudInstLire : public Noeud {
    // classe pour représenter un noeud "affectation"
    // composé de 2 fils : la variable et l'expression qu'on lui affecte
public:
    NoeudInstLire(Noeud* var); // construit une affectation

    ~NoeudInstLire() {
    } // à cause du destructeur virtuel de la classe Noeud
    int getValeur(); // évalue l'expression et affecte sa valeur à la variable
    void afficher(unsigned short indentation = 0); // affiche l'affectation

private:
    Noeud* variable;
};

class NoeudInstEcrire : public Noeud {
    // classe pour représenter un noeud "affectation"
    // composé de 2 fils : la variable et l'expression qu'on lui affecte
public:
    NoeudInstEcrire(Noeud* exp); // construit une affectation

    ~NoeudInstEcrire() {
    } // à cause du destructeur virtuel de la classe Noeud
    int getValeur(); // évalue l'expression et affecte sa valeur à la variable
    void afficher(unsigned short indentation = 0); // affiche l'affectation

private:
    Noeud* expression;
};

class NoeudInstEcrire_ligne : public Noeud {
    // classe pour représenter un noeud "affectation"
    // composé de 2 fils : la variable et l'expression qu'on lui affecte
public:
    NoeudInstEcrire_ligne(Noeud* exp); // construit une affectation

    ~NoeudInstEcrire_ligne() {
    } // à cause du destructeur virtuel de la classe Noeud
    int getValeur(); // évalue l'expression et affecte sa valeur à la variable
    void afficher(unsigned short indentation = 0); // affiche l'affectation

private:
    Noeud* expression;
};

class NoeudInstRepeter : public Noeud {
    // classe pour représenter un noeud "affectation"
    // composé de 2 fils : la variable et l'expression qu'on lui affecte
public:
    NoeudInstRepeter(Noeud* si, Noeud* exp); // construit une affectation

    ~NoeudInstRepeter() {
    } // à cause du destructeur virtuel de la classe Noeud
    int getValeur(); // évalue l'expression et affecte sa valeur à la variable
    void afficher(unsigned short indentation = 0); // affiche l'affectation

private:
    Noeud* SeqInst;
    Noeud* expression;
};

class NoeudInstPour : public Noeud {
    // classe pour représenter un noeud "affectation"
    // composé de 2 fils : la variable et l'expression qu'on lui affecte
public:
    NoeudInstPour(Noeud* var, Noeud* exp1, Noeud* exp2, Noeud* si); // construit une affectation

    ~NoeudInstPour() {
    } // à cause du destructeur virtuel de la classe Noeud
    int getValeur(); // évalue l'expression et affecte sa valeur à la variable
    void afficher(unsigned short indentation = 0); // affiche l'affectation

private:
    Noeud* variable;
    Noeud* expression1;
    Noeud* expression2;
    Noeud* SeqInst;
};

////////////////////////////////////////////////////////////////////////////////
// operateurs
////////////////////////////////////////////////////////////////////////////////

class NoeudOperateurOu : public Noeud {
    // classe pour représenter un noeud "opération arithmétique" composé d'un opérateur (+-*/)
    // et de 2 fils : l'opérande gauche et l'opérande droit
public:
    NoeudOperateurOu(Symbole operateur, Noeud* operandeGauche, Noeud* operandeDroit);
    // construit une opération binaire : operandeGauche operateur OperandeDroit

    ~NoeudOperateurOu() {
    } // à cause du destructeur virtuel de la classe Noeud
    int getValeur(); // évalue l'operande gauche, l'operande droit et applique l'opérateur
    void afficher(unsigned short indentation = 0); // affiche l'opération

private:
    Symbole operateur;
    Noeud* operandeGauche;
    Noeud* operandeDroit;
};


class NoeudOperateurEt : public Noeud {
    // classe pour représenter un noeud "opération arithmétique" composé d'un opérateur (+-*/)
    // et de 2 fils : l'opérande gauche et l'opérande droit
public:
    NoeudOperateurEt(Symbole operateur, Noeud* operandeGauche, Noeud* operandeDroit);
    // construit une opération binaire : operandeGauche operateur OperandeDroit

    ~NoeudOperateurEt() {
    } // à cause du destructeur virtuel de la classe Noeud
    int getValeur(); // évalue l'operande gauche, l'operande droit et applique l'opérateur
    void afficher(unsigned short indentation = 0); // affiche l'opération

private:
    Symbole operateur;
    Noeud* operandeGauche;
    Noeud* operandeDroit;
};

class NoeudOperateurBool : public Noeud {
    // classe pour représenter un noeud "opération arithmétique" composé d'un opérateur (+-*/)
    // et de 2 fils : l'opérande gauche et l'opérande droit
public:
    NoeudOperateurBool(Symbole operateur, Noeud* operandeGauche, Noeud* operandeDroit);
    // construit une opération binaire : operandeGauche operateur OperandeDroit

    ~NoeudOperateurBool() {
    } // à cause du destructeur virtuel de la classe Noeud
    int getValeur(); // évalue l'operande gauche, l'operande droit et applique l'opérateur
    void afficher(unsigned short indentation = 0); // affiche l'opération

private:
    Symbole operateur;
    Noeud* operandeGauche;
    Noeud* operandeDroit;
};

class NoeudOperateurAdd : public Noeud {
    // classe pour représenter un noeud "opération arithmétique" composé d'un opérateur (+-*/)
    // et de 2 fils : l'opérande gauche et l'opérande droit
public:
    NoeudOperateurAdd(Symbole operateur, Noeud* operandeGauche, Noeud* operandeDroit);
    // construit une opération binaire : operandeGauche operateur OperandeDroit

    ~NoeudOperateurAdd() {
    } // à cause du destructeur virtuel de la classe Noeud
    int getValeur(); // évalue l'operande gauche, l'operande droit et applique l'opérateur
    void afficher(unsigned short indentation = 0); // affiche l'opération

private:
    Symbole operateur;
    Noeud* operandeGauche;
    Noeud* operandeDroit;
};

class NoeudOperateurMult : public Noeud {
    // classe pour représenter un noeud "opération arithmétique" composé d'un opérateur (+-*/)
    // et de 2 fils : l'opérande gauche et l'opérande droit
public:
    NoeudOperateurMult(Symbole operateur, Noeud* operandeGauche, Noeud* operandeDroit);
    // construit une opération binaire : operandeGauche operateur OperandeDroit

    ~NoeudOperateurMult() {
    } // à cause du destructeur virtuel de la classe Noeud
    int getValeur(); // évalue l'operande gauche, l'operande droit et applique l'opérateur
    void afficher(unsigned short indentation = 0); // affiche l'opération

private:
    Symbole operateur;
    Noeud* operandeGauche;
    Noeud* operandeDroit;
};

class NoeudOperateurUnaire : public Noeud {
    // classe pour représenter un noeud "opération arithmétique" composé d'un opérateur (+-*/)
    // et de 2 fils : l'opérande gauche et l'opérande droit
public:
    NoeudOperateurUnaire(Symbole operateur, Noeud* operandeGauche, Noeud* operandeDroit);
    // construit une opération binaire : operandeGauche operateur OperandeDroit

    ~NoeudOperateurUnaire() {
    } // à cause du destructeur virtuel de la classe Noeud
    int getValeur(); // évalue l'operande gauche, l'operande droit et applique l'opérateur
    void afficher(unsigned short indentation = 0); // affiche l'opération

private:
    Symbole operateur;
    Noeud* operandeGauche;
    Noeud* operandeDroit;
};




#endif /* ARBRE_H_ */
